package com.example.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.entity.AuditLog;
import com.example.util.DateUtil;
import com.example.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.json.JsonArray;
import java.io.IOException;
import java.util.*;

/**
 * @author chenjiawen
 * @version 1.0
 * @date 2022/6/30 14:51
 */

@Slf4j
@RestController
public class ESController {

    @Autowired
    private RestHighLevelClient client;

    @PostMapping(path = "/logDeleteAllTest")
    public void logDeleteAllTest() {
        CountRequest countRequest = new CountRequest("audit_log");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.mustNot(QueryBuilders.matchQuery("extendInteger1", 1));
        searchSourceBuilder.query(boolQueryBuilder);
        countRequest.source(searchSourceBuilder);
        try {
            CountResponse countResponse = client.count(countRequest, RequestOptions.DEFAULT);
            RestStatus status = countResponse.status(); // ES请求状态
            if (status == RestStatus.OK) {
                long count = countResponse.getCount();
                System.out.println(count);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @PostMapping(path = "/logForwardTest")
    public void logForwardTest() {
        BulkRequest bulkRequest = new BulkRequest();
        List<AuditLog> auditLogList = new ArrayList<>();
        AuditLog auditLog = new AuditLog();
        auditLog.setCollectionType("logstash");
        auditLog.setCollectionAddress("192.168.182.203");
        auditLog.setEventMessage("<14>Fri Jun 24 2022 21:21:36 192.168.182.151 科来网络全流量安全分析系统 - 服务器:触发时间：2022-06-24 21:21:36 链路名称：烽火创新谷 警报名称：挖矿数据流特征值警报 警报等级：低 警报种类：信息收集 触发条件：HTTP OPTIONS方法 警报类型：数据流特征值警报 源IP地址：34.56.54.38 源端口：1234 目标IP地址：20.254.182.204 目标端口：4321 累计触发次数：1");
        auditLogList.add(auditLog);
        for (AuditLog audit : auditLogList) {
            //批量删除需要指定到具体的索引
            UpdateRequest request = new UpdateRequest().index("audit_log_20220629").id("aYiFq4EBtrhPegMHxaPe");
            audit.setExtendInteger2(null);
            Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(audit), Map.class);
            request.doc(map, XContentType.JSON);
            bulkRequest.add(request);
            try {
                BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
                if (bulk.hasFailures()) {
                    log.error("es更新存在错误");
                    log.error(bulk.buildFailureMessage());
                }
                log.info("ES重新解析删除未解析日志数据耗时：" + bulk.getTook().getSeconds() + "秒" + ",成功转发条数:" + auditLogList.size());
            } catch (IOException e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }

    @PostMapping(path = "/logForwardDelete")
    public void logForwardDelete() {
        BulkRequest bulkRequest = new BulkRequest();
        List<AuditLog> auditLogList = new ArrayList<>();
        AuditLog auditLog = new AuditLog();
        auditLog.setCollectionType("logstash");
        auditLog.setCollectionAddress("192.168.182.203");
        auditLog.setEventMessage("<14>Fri Jun 24 2022 21:21:36 192.168.182.151 科来网络全流量安全分析系统 - 服务器:触发时间：2022-06-24 21:21:36 链路名称：烽火创新谷 警报名称：挖矿数据流特征值警报 警报等级：低 警报种类：信息收集 触发条件：HTTP OPTIONS方法 警报类型：数据流特征值警报 源IP地址：34.56.54.38 源端口：1234 目标IP地址：20.254.182.204 目标端口：4321 累计触发次数：1");
        auditLogList.add(auditLog);
        for (AuditLog audit : auditLogList) {
            //批量删除需要指定到具体的索引
            DeleteRequest request = new DeleteRequest().index("audit_log_20220629").id("aYiFq4EBtrhPegMHxaPe");
            bulkRequest.add(request);
            try {
                BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
                if (bulk.hasFailures()) {
                    log.error("es更新存在错误");
                    log.error(bulk.buildFailureMessage());
                }
                log.info("ES重新解析删除未解析日志数据耗时：" + bulk.getTook().getSeconds() + "秒" + ",成功转发条数:" + auditLogList.size());
            } catch (IOException e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }


    @PostMapping(path = "/deleteIndex")
    public void deleteIndex() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        GetAliasesRequest request = new GetAliasesRequest();
        request.indices("audit_log");
        GetAliasesResponse response = client.indices().getAlias(request, RequestOptions.DEFAULT);
        Map<String, Set<AliasMetaData>> map = response.getAliases();
        Set<String> indices = map.keySet();
        Set<String> inSets = new HashSet<>();
        for (String str : indices) {
            String[] sp = str.split("_");
            try {
                if (isNumber(sp[sp.length - 1])) {
                    int num = Integer.parseInt(sp[sp.length - 1]);
                    if (num < 20220530) {
                        inSets.add(str);
                    }
                }
            } catch (Exception e) {
                // e.printStackTrace();
            }
        }

        for (String str : inSets) {
            DeleteRequest deleteRequest = new DeleteRequest().index(str);
            bulkRequest.add(deleteRequest);
            try {
                BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
                if (bulk.hasFailures()) {
                    log.error("es删除失败");
                    log.error(bulk.buildFailureMessage());
                }
            } catch (IOException e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }


    private boolean isNumber(String str) {
        String reg = "^[0-9]+(.[0-9]+)?$";
        return str.matches(reg);
    }

    @PostMapping(path = "/getAuditLog")
    public void getAuditLog(String id, String triggerStartTime) {
        Long startTime = System.currentTimeMillis();
        Date date = DateUtils.parse(triggerStartTime);
        //String indexName = "tsa_flow_" + DateUtil.date2Str(date, "yyyyMMdd");
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//        boolQueryBuilder.must(QueryBuilders.termsQuery("id", id));
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.size(10000);
        SearchRequest searchRequest = new SearchRequest("audit_log");
        searchRequest.source(sourceBuilder);
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            if (null == searchResponse) {
                return;
            }

            JSONObject jsonObject;
            SearchHit[] searchHits = searchResponse.getHits().getHits();
            for (SearchHit hit : searchHits) {
                System.out.println("search -> " + hit.getSourceAsString());
                System.out.println("search -> " + hit.getSourceAsMap().get("doc"));
                jsonObject = JSONObject.parseObject(hit.getSourceAsString());
                System.out.println(jsonObject.toString());
            }


        } catch (IOException e) {
            e.printStackTrace();
        }
        Long endTime = System.currentTimeMillis() - startTime;
    }
}